import { ref, onMounted, nextTick, reactive } from 'vue';
import {
  addClass,
  debounce,
  getEventTargetNode,
  getViewportOffset,
  pinyin,
  removeClass,
} from '@jecloud/utils';
import { useMenuStore } from '@/stores/menu-store';
import { computed } from 'vue';
import { watch } from 'vue';
import { onUnmounted } from 'vue';
import { openMenu } from '@/hooks/use-menu';
export function useGlobalSearch({ props, context }) {
  const { expose } = context;
  const menuStore = useMenuStore();
  const searchRef = ref();
  const state = reactive({
    visible: false,
    keyword: '',
    loadingText: '',
    searchMenus: [],
    historyMenus: computed(() => {
      return menuStore.computeHistoryMenus.filter((item, index) => index < 12);
    }),
  });

  const $search = {
    state,
    searchRef,
    selectedCls: 'is-selected',
    /**
     * 获得选中的数据
     * @param {*} first
     * @returns
     */
    getSelection(first) {
      return searchRef.value.querySelector(
        '.result-content .result-content-item' + (first ? '' : '.' + this.selectedCls),
      );
    },
    /**
     * 选择数据
     * @param {*} direction 导航方向
     */
    setSelected(direction) {
      let item = $search.getSelection();
      let selectItem;
      if (item) {
        // 有选中的数据，进行导航选择
        if (direction == 'next') {
          selectItem = item.nextElementSibling;
        } else {
          selectItem = item.previousElementSibling;
        }
        if (selectItem) {
          removeClass(item, this.selectedCls);
          addClass(selectItem, this.selectedCls);
        }
      } else {
        // 没有选中的数据，默认第一条
        selectItem = $search.getSelection(true);
        addClass(selectItem, this.selectedCls);
      }
      // 滚动定位
      if (selectItem) {
        const top = 63; // 距离顶部位置
        const resultDom = searchRef.value.querySelector('.result-content'); // 结果容器
        resultDom.style['scroll-behavior'] = 'smooth'; // 锚点动画
        resultDom.scrollTop = selectItem.offsetTop - top; // 滚动
      }
    },
    /**
     * 显示
     * @param {*} param0
     */
    show({ event }) {
      const box = getViewportOffset(event.currentTarget);
      searchRef.value.style.right = `${box.right}px`;
      state.visible = true;
      nextTick(() => {
        searchRef.value.querySelector('.ant-input').focus();
      });
    },
    /**
     * 隐藏
     */
    hide() {
      state.visible = false;
      state.keyword = '';
    },
    /**
     * 打开功能
     * @param {*} id
     */
    openMenu(id) {
      const menu = menuStore.getMenuById(id);
      if (menu) {
        openMenu(menu);
        $search.hide();
      }
    },
  };

  expose($search);
  // 执行搜索
  const doSearch = debounce(() => {
    let keyword = state.keyword.toLocaleLowerCase();
    state.searchMenus = keyword
      ? menuStore.searchMenus.filter((item) => {
          const text = item.text?.toLocaleLowerCase() ?? '';
          const pinyinText = pinyin(text, 'pinyin');
          return text.includes(keyword) || pinyinText.includes(keyword);
        })
      : [];
    state.loadingText = state.searchMenus.length > 0 ? '' : '暂无数据';
  }, 300);
  watch(
    () => state.keyword,
    () => {
      state.loadingText = '加载中...';
      doSearch();
    },
  );
  // 打开菜单
  const onMenuClick = (menu) => {
    $search.openMenu(menu.id);
  };
  // 点击reset会导致搜索框关闭，所以禁掉事件
  const onBeforeReset = () => {
    event.stopPropagation();
  };
  // 点击其他地方，关闭搜索页面
  const bodyClick = function (event) {
    onBodyClick({ event, $search });
  };
  // 键盘导航
  const inputKeyDown = function (event) {
    onInputKeyDown({ event, $search });
  };
  onMounted(() => {
    nextTick(() => {
      // 绑定事件
      document.body.addEventListener('click', bodyClick);
      searchRef.value.querySelector('.ant-input').addEventListener('keydown', inputKeyDown);
    });
  });
  onUnmounted(() => {
    // 解除事件
    document.body.removeEventListener('click', bodyClick);
    searchRef.value?.querySelector('.ant-input').removeEventListener('keydown', inputKeyDown);
  });

  return { state, searchRef, onBeforeReset, onMenuClick };
}

function onBodyClick({ event, $search }) {
  const { searchRef } = $search;
  const actionClick = getEventTargetNode(event, searchRef.value.parentNode, 'action-search').flag;
  const searchClick = getEventTargetNode(event, searchRef.value, 'admin-global-search').flag;
  if (!actionClick && !searchClick) {
    $search.hide();
  }
}

function onInputKeyDown({ event, $search }) {
  const keyCode = event.keyCode || event.which;
  switch (keyCode) {
    case 38: // 上箭头
      $search.setSelected('prev');
      break;
    case 40: // 下箭头
      $search.setSelected('next');
      break;
    case 13: // 确认
      $search.openMenu($search.getSelection()?.id);
      break;
  }
}
